﻿namespace BLP2API
{
    using System;
    using System.IO;
    using System.Runtime.InteropServices;

    public class BLP2Parse
    {
        private static MemoryStream BLP2toDXT1(byte[] blp2)
        {
            BLP2_HEADER blp_header;
            int num;
            MemoryStream input = new MemoryStream(blp2);
            BinaryReader reader = new BinaryReader(input);
            blp_header.ident = reader.ReadBytes(4);
            blp_header.compress = reader.ReadInt32();
            blp_header.flags = reader.ReadBytes(4);
            blp_header.width = reader.ReadInt32();
            blp_header.height = reader.ReadInt32();
            blp_header.mipmapOffsets = new int[0x10];
            for (num = 0; num < 0x10; num++)
            {
                blp_header.mipmapOffsets[num] = reader.ReadInt32();
            }
            blp_header.mipmapLengths = new int[0x10];
            for (num = 0; num < 0x10; num++)
            {
                blp_header.mipmapLengths[num] = reader.ReadInt32();
            }
            int num2 = blp_header.width * blp_header.height;
            if (blp_header.compress == 1)
            {
                RGBA_PIXEL[] rgba_pixelArray = new RGBA_PIXEL[0x100];
                for (int i = 0; i < 0x100; i++)
                {
                    rgba_pixelArray[i].R = reader.ReadByte();
                    rgba_pixelArray[i].G = reader.ReadByte();
                    rgba_pixelArray[i].B = reader.ReadByte();
                    rgba_pixelArray[i].A = reader.ReadByte();
                }
                input.Seek((long) blp_header.mipmapOffsets[0], SeekOrigin.Begin);
                if (blp_header.flags[0] == 1)
                {
                    return null;
                }
                if (blp_header.flags[0] == 2)
                {
                    if (blp_header.flags[1] == 8)
                    {
                        return null;
                    }
                    MemoryStream stream = new MemoryStream();
                    stream.WriteByte(0x44);
                    stream.WriteByte(0x44);
                    stream.WriteByte(0x53);
                    stream.WriteByte(0x20);
                    stream.WriteByte(0x7c);
                    for (num = 0; num < 3; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(7);
                    stream.WriteByte(0x10);
                    for (num = 0; num < 3; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(1);
                    for (num = 0; num < 3; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(1);
                    for (num = 0; num < 0x3a; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(0x20);
                    for (num = 0; num < 3; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(4);
                    for (num = 0; num < 3; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(0x44);
                    stream.WriteByte(0x58);
                    stream.WriteByte(0x54);
                    stream.WriteByte(0x31);
                    for (num = 0; num < 0x15; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.WriteByte(0x10);
                    for (num = 0; num < 0x12; num++)
                    {
                        stream.WriteByte(0);
                    }
                    stream.Write(blp2, blp_header.mipmapOffsets[0], blp_header.mipmapLengths[0]);
                    return stream;
                }
            }
            return null;
        }

        private static MemoryStream BLP2toTGA(byte[] blp2)
        {
            BLP2_HEADER blp_header;
            int num;
            MemoryStream dest = new MemoryStream();
            MemoryStream input = new MemoryStream(blp2);
            BinaryReader reader = new BinaryReader(input);
            blp_header.ident = reader.ReadBytes(4);
            blp_header.compress = reader.ReadInt32();
            blp_header.flags = reader.ReadBytes(4);
            blp_header.width = reader.ReadInt32();
            blp_header.height = reader.ReadInt32();
            blp_header.mipmapOffsets = new int[0x10];
            for (num = 0; num < 0x10; num++)
            {
                blp_header.mipmapOffsets[num] = reader.ReadInt32();
            }
            blp_header.mipmapLengths = new int[0x10];
            for (num = 0; num < 0x10; num++)
            {
                blp_header.mipmapLengths[num] = reader.ReadInt32();
            }
            int num2 = blp_header.width * blp_header.height;
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(2);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(0);
            dest.WriteByte(1);
            dest.WriteByte(0);
            dest.WriteByte(1);
            dest.WriteByte(0x20);
            dest.WriteByte(8);
            if (blp_header.compress == 1)
            {
                RGBA_PIXEL[] rgba_pixelArray = new RGBA_PIXEL[0x100];
                for (int i = 0; i < 0x100; i++)
                {
                    rgba_pixelArray[i].R = reader.ReadByte();
                    rgba_pixelArray[i].G = reader.ReadByte();
                    rgba_pixelArray[i].B = reader.ReadByte();
                    rgba_pixelArray[i].A = reader.ReadByte();
                }
                input.Seek((long) blp_header.mipmapOffsets[0], SeekOrigin.Begin);
                if (blp_header.flags[0] != 1)
                {
                    if (blp_header.flags[0] != 2)
                    {
                        return dest;
                    }
                    if (blp_header.flags[1] == 8)
                    {
                        DecodeDDSFormat(4, input, blp_header.width, blp_header.height, dest);
                        return dest;
                    }
                    DecodeDDSFormat(2, input, blp_header.width, blp_header.height, dest);
                }
                return dest;
            }
            if (blp_header.compress == 0)
            {
            }
            return dest;
        }

        public static MemoryStream BLPtoDXT1(byte[] blp)
        {
            if (((blp[0] == 0x42) && (blp[1] == 0x4c)) && (blp[2] == 80))
            {
                if (blp[3] == 0x31)
                {
                }
                if (blp[3] == 50)
                {
                    return BLP2toDXT1(blp);
                }
            }
            return null;
        }

        public static MemoryStream BLPtoTGA(byte[] blp)
        {
            if (((blp[0] == 0x42) && (blp[1] == 0x4c)) && (blp[2] == 80))
            {
                if (blp[3] == 0x31)
                {
                }
                if (blp[3] == 50)
                {
                    return BLP2toTGA(blp);
                }
            }
            return null;
        }

        private static bool DecodeDDSFormat(int nFormat, MemoryStream src, int width, int height, MemoryStream dest)
        {
            int num2;
            int num3;
            int length = (int) dest.Length;
            if (nFormat == 0)
            {
                for (num2 = 0; num2 < height; num2++)
                {
                    num3 = 0;
                    while (num3 < width)
                    {
                        dest.WriteByte((byte) src.ReadByte());
                        dest.WriteByte((byte) src.ReadByte());
                        dest.WriteByte((byte) src.ReadByte());
                        dest.WriteByte(0xff);
                        num3++;
                    }
                }
            }
            else if (nFormat != 1)
            {
                BinaryReader reader = new BinaryReader(src);
                int num4 = (width < 4) ? width : 4;
                int num5 = (height < 4) ? height : 4;
                for (num2 = 0; num2 < height; num2 += num5)
                {
                    for (num3 = 0; num3 < width; num3 += num4)
                    {
                        ulong num6 = 0L;
                        uint num7 = 0;
                        uint num8 = 0;
                        if (nFormat == 4)
                        {
                            num6 = reader.ReadUInt64();
                        }
                        else if (nFormat == 6)
                        {
                            num6 = reader.ReadUInt64();
                            num7 = (uint) (num6 & ((ulong) 0xffL));
                            num8 = (uint) ((num6 >> 8) & ((ulong) 0xffL));
                        }
                        uint num9 = reader.ReadUInt16();
                        uint num10 = reader.ReadUInt16();
                        DDS_COLOR[] dds_colorArray = new DDS_COLOR[4];
                        dds_colorArray[0].b = (byte) (((num9 >> 11) & 0x1f) << 3);
                        dds_colorArray[0].g = (byte) (((num9 >> 5) & 0x3f) << 2);
                        dds_colorArray[0].r = (byte) ((num9 & 0x1f) << 3);
                        dds_colorArray[1].b = (byte) (((num10 >> 11) & 0x1f) << 3);
                        dds_colorArray[1].g = (byte) (((num10 >> 5) & 0x3f) << 2);
                        dds_colorArray[1].r = (byte) ((num10 & 0x1f) << 3);
                        if (num9 > num10)
                        {
                            dds_colorArray[2].r = (byte) (((dds_colorArray[0].r * 2) + dds_colorArray[1].r) / 3);
                            dds_colorArray[2].g = (byte) (((dds_colorArray[0].g * 2) + dds_colorArray[1].g) / 3);
                            dds_colorArray[2].b = (byte) (((dds_colorArray[0].b * 2) + dds_colorArray[1].b) / 3);
                            dds_colorArray[3].r = (byte) ((dds_colorArray[0].r + (dds_colorArray[1].r * 2)) / 3);
                            dds_colorArray[3].g = (byte) ((dds_colorArray[0].g + (dds_colorArray[1].g * 2)) / 3);
                            dds_colorArray[3].b = (byte) ((dds_colorArray[0].b + (dds_colorArray[1].b * 2)) / 3);
                        }
                        else
                        {
                            dds_colorArray[2].r = (byte) ((dds_colorArray[0].r + dds_colorArray[1].r) / 2);
                            dds_colorArray[2].g = (byte) ((dds_colorArray[0].g + dds_colorArray[1].g) / 2);
                            dds_colorArray[2].b = (byte) ((dds_colorArray[0].b + dds_colorArray[1].b) / 2);
                            dds_colorArray[3].r = 0;
                            dds_colorArray[3].g = 0;
                            dds_colorArray[3].b = 0;
                        }
                        for (int i = 0; i < num5; i++)
                        {
                            uint num12 = reader.ReadByte();
                            dest.Seek((long) ((((width * (num2 + i)) + num3) * 4) + length), SeekOrigin.Begin);
                            for (int j = 0; j < num4; j++)
                            {
                                dest.WriteByte(dds_colorArray[(int) ((IntPtr) (num12 & 3))].r);
                                dest.WriteByte(dds_colorArray[(int) ((IntPtr) (num12 & 3))].g);
                                dest.WriteByte(dds_colorArray[(int) ((IntPtr) (num12 & 3))].b);
                                if (nFormat == 2)
                                {
                                    dest.WriteByte((((num12 & 3) == 3) && (num9 <= num10)) ? ((byte) 0) : ((byte) 0xff));
                                }
                                else if (nFormat == 4)
                                {
                                    dest.WriteByte((byte) ((num6 & 15L) << 4));
                                    num6 = num6 >> 4;
                                }
                                else if (nFormat == 6)
                                {
                                    uint num14 = (byte) (num6 & ((ulong) 7L));
                                    if (num14 == 0)
                                    {
                                        dest.WriteByte((byte) num7);
                                    }
                                    else if (num14 == 1)
                                    {
                                        dest.WriteByte((byte) num8);
                                    }
                                    else if (num7 > num8)
                                    {
                                        dest.WriteByte((byte) ((((8 - num14) * num7) + ((num14 - 1) * num8)) / 7));
                                    }
                                    else if (num14 > 5)
                                    {
                                        dest.WriteByte((num14 == 6) ? ((byte) 0) : ((byte) 0xff));
                                    }
                                    else
                                    {
                                        dest.WriteByte((byte) ((((6 - num14) * num7) + ((num14 - 1) * num8)) / 5));
                                    }
                                    num6 = num6 >> 3;
                                }
                                else
                                {
                                    dest.WriteByte(0xff);
                                }
                                num12 = num12 >> 2;
                            }
                        }
                    }
                }
            }
            return true;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct BLP2_HEADER
        {
            public byte[] ident;
            public int compress;
            public byte[] flags;
            public int width;
            public int height;
            public int[] mipmapOffsets;
            public int[] mipmapLengths;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct DDS_COLOR
        {
            public byte r;
            public byte g;
            public byte b;
        }

        private enum DDS_Format
        {
            DDS_DXT1 = 2,
            DDS_DXT2 = 3,
            DDS_DXT3 = 4,
            DDS_DXT4 = 5,
            DDS_DXT5 = 6,
            DDS_ERROR = -1,
            DDS_RGB = 0,
            DDS_RGBA = 1
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RGBA_PIXEL
        {
            public byte R;
            public byte G;
            public byte B;
            public byte A;
        }
    }
}

